﻿using HCMS.CommonDtos;
using HCMS.Entities.Manage;
using HCMS.Extensions;
using HCMS.IServices.Manage;
using HCMS.Utils;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;

namespace HCMS.Web.Manage.Filter
{
    /// <summary>
    /// 全局 异常处理 过滤器
    /// </summary>
    public class GlobalExceptionFilter : IAsyncExceptionFilter
    {
        private readonly IHostEnvironment _hostEnvironment;
        private readonly IAdminActionLogsAppService adminActionLogsAppService;

        public GlobalExceptionFilter(
            IHostEnvironment _hostEnvironment,
            IAdminActionLogsAppService adminActionLogsAppService
            )
        {
            this._hostEnvironment = _hostEnvironment;
            this.adminActionLogsAppService = adminActionLogsAppService;
        }

        /// <summary>
        /// 异常处理方法
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task OnExceptionAsync(ExceptionContext context)
        {
            var exceptionInfo = context.Exception;

            #region 操作日志
            AdminActionLogs? adminActionLogs = null;
            var logs = context.HttpContext.Items["adminActionLogs"].ToString("");
            if (!string.IsNullOrWhiteSpace(logs))
            {
                adminActionLogs = JsonConvert.DeserializeObject<AdminActionLogs>(logs) ?? new AdminActionLogs();
                adminActionLogs.EndTime = DateTime.Now;
                var differenTime = DateTimeUtil.DifferenTimespan(adminActionLogs.StartTime, adminActionLogs.EndTime);
                adminActionLogs.ExecutionTime = differenTime.Milliseconds;
            }
            #endregion

            #region 自定义友好异常 处理
            if ((exceptionInfo is HCMS.Extensions.UserFriendlyException) ||
                (exceptionInfo is Volo.Abp.UserFriendlyException))
            {
                var isAjax = context.HttpContext.Request.IsAjax();
                if (isAjax)
                {
                    var jsonResult = new JsonResult(
                        new AjaxResultDto() { Code = 500, Message = exceptionInfo.Message }
                    );
                    context.Result = jsonResult;
                }
                else
                {
                    var contentResult = new ContentResult()
                    {
                        StatusCode = StatusCodes.Status500InternalServerError,
                        ContentType = "text/plain",
                        Content = exceptionInfo.Message
                    };
                    context.Result = contentResult;
                }

                #region 记录 操作日志【结束】
                // 方法抛出友好异常：系统在这里记录 操作日志
                // 方法正常运行并返回：系统在【结果 执行 过滤器】记录 操作日志
                if (adminActionLogs != null)
                {
                    adminActionLogs.ResultInfo = $"操作失败。系统返回提示：{exceptionInfo.Message}";
                    await adminActionLogsAppService.BaseInsertAsync(adminActionLogs);
                }
                #endregion
            }
            #endregion

            #region 其它系统异常 处理
            else
            {
                // 记录异常日志
                var errorMsg = new List<string> { 
                    "系统全局异常"
                };

                #region 同时记录 操作日志
                if (adminActionLogs != null)
                {
                    adminActionLogs.ResultInfo = "";
                    errorMsg.Add(string.Format("请求参数：【{0}】", JsonConvert.SerializeObject(adminActionLogs).Replace(",", ",\r\n")));
                }
                #endregion

                Log4NetUtil.Error(string.Join("\r\n", errorMsg), exceptionInfo, out string errorId);

                // 异常信息
                var messageContent = "";

                // 开发环境，显示具体异常信息
                if (_hostEnvironment.IsDevelopment())
                {
                    messageContent = exceptionInfo.ToString();
                }
                // 不是开发环境，显示友好消息
                else
                {
                    messageContent = $"发生了一个错误，错误Id[{errorId}]。我们已经记录了这个问题，并正在修复。";
                }

                var isAjax = context.HttpContext.Request.IsAjax();
                if (isAjax)
                {
                    var jsonResult = new JsonResult(
                        new AjaxResultDto() { Code = 500, Message = messageContent }
                    );
                    context.Result = jsonResult;
                }
                else
                {
                    var result = new ContentResult
                    {
                        StatusCode = StatusCodes.Status500InternalServerError,
                        ContentType = "text/plain",
                        Content = messageContent
                    };
                    // 返回消息
                    context.Result = result;
                }
            }
            #endregion

            // 指示异常处理已经完成
            context.ExceptionHandled = true;
        }
    }
}